﻿using SourceMaster.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LibGit2Sharp;

namespace SourceMaster.Util
{
    public class RepoUtil
    {
        public static Patch GetPatchForCommit(Repository repo, MyCommit myCommit)
        {
            Tree thisTree = ((Commit)repo.Lookup(myCommit.ObjectId)).Tree;
            Tree parentTree = ((Commit)repo.Lookup(myCommit.Parents.ElementAt(0).ObjectId)).Tree;
            return repo.Diff.Compare<Patch>(thisTree, parentTree);
        }

        public static LibGit2Sharp.TreeChanges GetTreeChangesForCommit(LibGit2Sharp.Repository repo, MyCommit myCommit)
        {
            LibGit2Sharp.Tree thisTree = ((Commit)repo.Lookup(myCommit.ObjectId)).Tree;
            LibGit2Sharp.Tree parentTree = ((Commit)repo.Lookup(myCommit.Parents.ElementAt(0).ObjectId)).Tree;

            return repo.Diff.Compare<TreeChanges>(thisTree, parentTree);
        }

        public static List<MyBranch> GetBranchesAroundCommit(MyCommit myCommit, ObservableCollection<MyBranch> myBranches)
        {
            List<MyBranch> myBranchList = new List<MyBranch>();

            foreach (MyBranch myBranch in myBranches)
            {
                if (myBranch.Tip == null || myBranchList.Any(b => myBranch.Tip.Branches.Contains(b))
                    || myBranchList.Any(b => b.Tip.Branches.Contains(myBranch)))
                {
                    continue;
                }

                if(myBranch.Tip.Date >= myCommit.Date)
                {
                    myBranchList.Add(myBranch);
                }
                else
                {
                    if (!myBranch.Tip.Branches.Any(b => myCommit.Branches.Contains(b)))
                        myBranchList.Add(myBranch);
                }
            }
            return myBranchList;
                    
        }

        public static void IncrementCommitVisualPosition(MyCommit myCommit, int level = 0)
        {
            if (myCommit == null || myCommit.VisualPosition != -1)
                return;

            if (myCommit.Children.Count > 1 && level > 0)
                return;

            myCommit.VisualPosition = level;

            myCommit.Branches.ForEach(b =>
            {
                if (b.RightMostVisualPosition < level)
                    b.RightMostVisualPosition = level;
            });

            if(myCommit.IsMergeCommit())
            {
                int i = 0;
                foreach(MyCommit parentCommit in myCommit.Parents)
                {
                    RepoUtil.IncrementCommitVisualPosition(parentCommit, level + i);
                    i++;
                }
            }
            else if(myCommit.Parents.Count>0)
            {
                //RepoUtil.IncrementCommitVisualPosition(myCommit.Parents.ElementAt(0), level);
                RepoUtil.IncrementCommitVisualPosition(myCommit.Parents.ElementAt(0));
            }
        }

        public static IEnumerable<MyBranch> GetBranchesThatTrack(MyBranch branch, ObservableCollection<MyBranch> branches)
        {
            return branches.Where(b => b.TrackedBranch == branch);
        }
    }
}
